API GatewayのリソースポリシーでAPIにアクセスできる送信元IPアドレスを制限する
データアナリティクス事業本部の貞松です。
案件絡みで発生した調べごとの備忘録的なやつです。
API GatewayからデプロイしたパブリックなAPIがあまりにも無防備なので、せめて送信元IPアドレスで制限したいと思い、調べてみたところリソースポリシーでサックリ設定できそうなのでやってみました。
API Gatewayで適当なAPIをデプロイ
確認の為にAPI Gatewayに適当なAPIをデプロイしておきます。
今回はアクセス制御を確認するだけなので、特に中身のないAPIです。
GETでアクセスすると "hello" と返ってくるだけです。
この段階では特に何事もなくアクセスできています。
API Gatewayのリソースポリシーを設定
API Gatewayのリソースポリシーを作成・更新するための権限
API Gatewayのリソースポリシーを作成・更新するためには、apigateway:UpdateRestApiPolicy
だけでなくapigateway:PATCH
権限が必要です。
API Gatewayのリソースポリシーの作成
次にAPI Gatewayのリソースポリシーを設定していきます。
初期状態のリソースポリシー画面は空っぽの状態です。
実はリソースポリシー画面の下部に制御するパターンに応じたテンプレートを展開してくれるボタンがあるので、今回の要件に対しては「IP Range Denylist」をクリックして、展開されたテンプレートを編集すれば簡単に設定ができます。
展開されたコードは以下の通りです。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Deny", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "execute-api:/{{stageNameOrWildcard}}/{{httpVerbOrWildcard}}/{{resourcePathOrWildcard}}", "Condition" : { "IpAddress": { "aws:SourceIp": [ "{{sourceIpOrCIDRBlock}}", "{{sourceIpOrCIDRBlock}}" ] } } }, { "Effect": "Allow", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "execute-api:/{{stageNameOrWildcard}}/{{httpVerbOrWildcard}}/{{resourcePathOrWildcard}}" } ] }
Resource
の指定execute-api:/{{stageNameOrWildcard}}/{{httpVerbOrWildcard}}/{{resourcePathOrWildcard}}
の箇所- リソース個別に指定する場合は、
execute-api:/dev/GET/hello
のような形式で指定します - リソースをまとめて指定する場合は、
execute-api:/*/*/*
のようにワイルドカードで指定します
aws:SourceIp
の指定- 個別のIPアドレスを指定、あるいはCIDRブロックを指定します
- リスト形式で複数指定することも可能です
Deny
設定内にあるCondition
の配下をIpAddress
にするとブラックリスト、NotIpAddress
にするとホワイトリストを設定することができます。逆で設定しないように注意してください。
ちなみにaws:SourceIp
は、パブリックAPIに対する外部の送信元IPアドレス指定に使用します。
プライベートAPIに対するVPCからの送信元IPアドレスを指定する場合は、代わりにaws:VpcSourceIp
を指定する点に注意してください。
リソースポリシーの記述が完了したら、右下のSaveボタンをクリックして設定を保存します。
リソースポリシー設定後にAPIを再デプロイする
リソースポリシーを設定した段階では、APIにポリシーが反映されません。必ずAPIの再デプロイを実行してください。
送信元IPアドレスをブラックリストに設定した場合の動作
Condition
の配下をIpAddress
として、送信元IPアドレスをaws:SourceIp
に指定してAPIを再デプロイします。
APIにアクセスすると以下の結果になります。
アクセスが拒否されました。
送信元IPアドレスをホワイトリストに設定した場合の動作
Condition
の配下をNotIpAddress
として、送信元IPアドレスをaws:SourceIp
に指定してAPIを再デプロイします。
APIにアクセスすると以下の結果になります。
正常にアクセスできました。
ちなみに送信元IPアドレスとは異なるアドレスを設定してみたところ、以下の通りちゃんとアクセスが拒否されました。
まとめ
API Gatewayのリソースポリシーでチョイチョイと設定するだけで送信元IPを制限することができました。
本格的なエンドポイント防御の為にはAWS WAFの導入を検討するのが良さそうですが、差し当たりのアクセス制限を施すにはこれでも良さそうです。